using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Net;
using System.IO;
using System.Threading;

namespace ChaosDL
{
	public partial class ProgramForm : Form
	{
		protected Thread _thread;

		public enum ColumnIndices
		{
			Name,
			Size,
			Status,
			Url,
			Max
		}

		public ProgramForm()
		{
			InitializeComponent();
		}

		private void _downloadButton_Click(object sender, EventArgs e)
		{
			string text = Clipboard.GetText();
			Uri url = new Uri(text);
			_fileList.Items.Insert(0, "");
			for(int emptyColumn = 0; emptyColumn < (int)ColumnIndices.Max; emptyColumn++)
			{
				_fileList.Items[0].SubItems.Add("");
			}
			string fileName = url.LocalPath;
			fileName = fileName.Replace("/", "" + Path.DirectorySeparatorChar);
			fileName = Path.GetFileName(fileName);
			_fileList.Items[0].SubItems[(int)ColumnIndices.Url].Text = text;
			_fileList.Items[0].SubItems[(int)ColumnIndices.Name].Text = fileName;
			_downloadUrl = text;
			string saveFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
			if (fileName.Length == 0)
			{
				fileName = "download.bin";
			}
			string savePath = Path.Combine(saveFolder, fileName);
			_savePath = savePath;
			_thread = new Thread(OnThread);
			_thread.Start();
		}

		protected delegate void DownloadNofityDelegate(int index, long downloadSize, long totalSize);
		protected DownloadNofityDelegate _downloadNotify;
		protected string _downloadUrl;
		protected string _savePath;

		protected void OnDownloadNofity(int index, long downloadSize, long totalSize)
		{
			long rate = (totalSize == 0 ? 0 : (downloadSize * 100 / totalSize));
			ListViewItem listItem = _fileList.Items[0];

			string downloadSizeText = "" + downloadSize;
			if (downloadSize > 10 * 1000000000L)
			{
				downloadSizeText = String.Format("{0}GB", downloadSize / 1000000000L);
			}
			else if (downloadSize > 10 * 1000000)
			{
				downloadSizeText = String.Format("{0}MB", downloadSize / 1000000);
			}
			else if (downloadSize > 10 * 1000)
			{
				downloadSizeText = String.Format("{0}KB", downloadSize / 1000);
			}

			string text = String.Format("{0}% {1}", rate, downloadSizeText);
			if (listItem.SubItems[(int)ColumnIndices.Status].Text != text)
			{
				listItem.SubItems[(int)ColumnIndices.Status].Text = text;
			}
			string totalSizeText = "" + totalSize;
			if (listItem.SubItems[(int)ColumnIndices.Size].Text != totalSizeText)
			{
				listItem.SubItems[(int)ColumnIndices.Size].Text = totalSizeText;
			}
		}

		protected void OnThread()
		{
			string savePath = _savePath;
			Uri url = new Uri(_downloadUrl);
			HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
			HttpWebResponse response = null;
			try
			{
				response = (HttpWebResponse)request.GetResponse();
			}
			catch (WebException we)
			{
				MessageBox.Show(we.ToString());
				return;
			}
			long contentLength = response.ContentLength;

			Invoke(_downloadNotify, new object[] { 0, 0, contentLength });

			byte[] buffer = new byte[1048576];
			long aliveSize = contentLength;
			using (Stream responseStream = response.GetResponseStream())
			{
				using (FileStream fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write))
				{
					while (aliveSize > 0)
					{
						int readSize = responseStream.Read(buffer, 0, buffer.Length);
						if (readSize == 0)
						{
							continue;
						}

						fileStream.Write(buffer, 0, readSize);
						aliveSize -= readSize;
						Invoke(_downloadNotify, new object[] { 0, contentLength - aliveSize, contentLength });
					}
				}
			}
			MessageBox.Show("Complete");

		}

		private void ProgramForm_Load(object sender, EventArgs e)
		{
			_downloadNotify += OnDownloadNofity;
		}
	}
}